/*********************************************************************
Copyright 2011 Chris Gardner

This file is part of CardLib.

CardLib is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

CardLib is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with CardLib.  If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/

using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace FreestyleCoding.CardLib {

	/// <summary>An interface to define a deck of cards</summary>
	/// <typeparam name="T">Any type of ICard</typeparam>
	public interface IDeck<T> : IEnumerable<T> where T : ICard {

		/// <summary>Cuts the deck</summary>
		/// <remarks>Picks a random place to cut</remarks>
		void Cut();

		/// <summary>Cuts the deck</summary>
		/// <param name="p_NumberOfCardsToCutFromTheTop">Number of cards to pull of the top to cut</param>
		/// <exception cref="ArgumentOutOfBoundsException">p_NumberOfCardsToCutFromTheTop is negative</exception>
		/// <exception cref="ArgumentOutOfBoundsException">p_NumberOfCardsToCutFromTheTop is greater than Length of IDeck</exception>
		void Cut( int p_NumberOfCardsToCutFromTheTop );

		/// <summary>Randomized the order of the cards in the deck</summary>
		void Shuffle();

		/// <summary>Draws the top card from the deck. The card is removed from the deck when it is drawn.</summary>
		/// <returns>The top ICard</returns>
		T Draw();

		/// <summary>Draws the top <paramref name="p_NumberOfCardsToDraw"/> cards from the deck. The cards are removed from the deck when they are drawn.</summary>
		/// <param name="p_NumberOfCardsToDraw">New number of cards to remove from the deck</param>
		/// <returns>A collections of ICards with a Length of <paramref name="p_NumberOfCardsToDraw"/>. If the IDeck currently has less than <paramref name="p_NumberOfCardsToDraw"/> cards, all cards are returned and the IDeck will be empty.</returns>
		Collection<T> Draw( int p_NumberOfCardsToDraw );

		/// <summary>Inserts the card onto the top of the deck</summary>
		/// <param name="p_CardToInsert">The card to insert into the deck</param>
		void Insert( ICard p_CardToInsert );

		/// <summary>Inserts the card into the specific place in the deck</summary>
		/// <param name="p_CardToInsert">The card to insert into the deck</param>
		/// <param name="p_Position">The position into the deck to place the card. If p_Position is negative or zero, it is inserted on top of the deck. If p_Position is greator than the size of the deck, it is placed as the last card.</param>
		void Insert( ICard p_CardToInsert, int p_Position );

		/// <summary>Places all the cards in <paramref name="p_DeckToInsertIntoThisDeck"/> into this IDeck.</summary>
		/// <param name="p_DeckToInsertIntoThisDeck">An IDeck to be merged with the current deck.</param>
		/// <remarks><paramref name="p_DeckToInsertIntoThisDeck"/> will be empty after this operation.</remarks>
		void Merge( IDeck<T> p_DeckToInsertIntoThisDeck );

		/// <summary>Specifies if the IDeck has any cards.</summary>
		/// <returns>true if the IDeck has cards, false if the IDeck is empty.</returns>
		bool HasCards { get; }
	}
}